package com.fm.demo.utils

import android.app.ActivityManager
import android.content.Context
import android.content.Context.ACTIVITY_SERVICE
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.media.MediaScannerConnection
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.provider.ContactsContract
import android.util.Log
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.RegexUtils
import com.blankj.utilcode.util.ToastUtils
import com.fm.demo.bean.MyContact
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.*
import java.nio.charset.Charset


/**
 * @CreateData:     2019/11/1 9:33
 * @E-Mail:         709674174@qq.com
 * @Author:         lyy
 * @Description:    常用方法
 */
object CommonUtils {


    /** 保存图片到本地，通知到图库 */
    suspend fun saveImage(context: Context, bitmap: Bitmap): Boolean {
        return withContext(Dispatchers.IO) {
            LogUtils.e("test3 thread : ${Thread.currentThread()}")
            val appDir = File(Environment.getExternalStorageDirectory().absolutePath, "ScreenShot")
            if (!appDir.exists()) {
                appDir.mkdir()
            }
            val fileName = System.currentTimeMillis().toString() + ".png"
            val file = File(appDir, fileName)
            try {
                //写入图片到本地文件
                var os: OutputStream? = null
                try {
                    os = BufferedOutputStream(FileOutputStream(file))
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, os)
                } catch (e: IOException) {
                    e.printStackTrace()
                } finally {
                    try {
                        os?.close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }

                }
                bitmap.recycle()
                // 图片复制，插入图库 会出现两个图片
                // MediaStore.Images.Media.insertImage(context.contentResolver, file.absolutePath, fileName, null)
                // context.sendBroadcast(
                //     Intent(
                //         Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                //         Uri.fromFile(file)
                //     )
                // )
                MediaScannerConnection.scanFile(
                    context,
                    arrayOf(file.path),
                    arrayOf("image/png"),
                    null
                )
                true
            } catch (e: Exception) {
                false
            }
        }
    }

    /**
     * 检查service是否运行
     * @param className service类名
     */
    fun checkServiceIsRun(context: Context, className: String): Boolean {
        val manager: ActivityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

        @Suppress("DEPRECATION")
        val servicesInfo = manager.getRunningServices(Int.MAX_VALUE)
        if (servicesInfo.isNullOrEmpty()) {
            return false
        }
        servicesInfo.forEach {
            if (it.service.className == className) {
                return true
            }
        }
        return false
    }

    /**
     * 主线程弹出吐司
     * @param content 内容
     */
    fun showToastShotMain(content: String) {
        Handler(Looper.getMainLooper()).post {
            ToastUtils.showShort(content)
        }
    }

    /**
     * 获取通讯录
     * @return 通讯录实体类集合
     */
    suspend fun getAllContacts(context: Context): ArrayList<MyContact> {
        return withContext(Dispatchers.IO) {
            val phones = ArrayList<MyContact>()
            val params = HashMap<String, String>()
            try {
                val cursor = context.contentResolver.query(
                    ContactsContract.Contacts.CONTENT_URI, arrayOf(
                        ContactsContract.Contacts._ID,
                        ContactsContract.Contacts.DISPLAY_NAME
                    ), null, null, null
                )
                cursor?.let { it ->
                    while (it.moveToNext()) {
                        val contactId = it.getLong(0)
                        //获取联系人姓名
                        val name = cursor.getString(1)
                        //获取联系人电话号码
                        val phoneCursor = context.contentResolver.query(
                            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                            arrayOf(ContactsContract.CommonDataKinds.Phone.NUMBER),
                            ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId,
                            null, null
                        )
                        phoneCursor?.let {
                            while (it.moveToNext()) {
                                var phone = it.getString(0)
                                params[phone] = name
                                if (phone.isNotEmpty() && phone.first().toString() == "+") {
                                    if (phone.length > 3) {
                                        phone = phone.substring(3)
                                    } else {
                                        phone.replace("+", "")
                                    }
                                }
                                val temPhone = StringBuilder()
                                for (num in phone) {
                                    if (RegexUtils.isMatch("^[0-9]", num.toString())) {
                                        temPhone.append(num)
                                    }
                                }
                                phones.add(MyContact(phoneNum = temPhone.toString()))
                            }
                        }
                        phoneCursor?.close()
                    }
                }
                cursor?.close()
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                LogUtils.e(params)
            }
            phones
        }
    }

    /**
     * 检查某个包 是否有自启动
     *
     * @invalid 测试无效
     *
     * @param context
     * @return 0 木有 1有自启动 2有小插件 3都有
     */
    suspend fun hasStartSelf(context: Context, packageName: String): Boolean {
        return withContext(Dispatchers.IO) {
            try {
                // 通过包名，返回包信息
                context.packageManager.checkPermission("android.permission.RECEIVE_BOOT_COMPLETED", packageName) == PackageManager.PERMISSION_GRANTED
            } catch (e: Exception) {
                false
            }

        }
    }

    /** 
     * 执行具体的静默安装逻辑，需要手机ROOT。 
     * @param apkPath  要安装的apk文件的路径 
     * @return 安装成功返回true，安装失败返回false。 
     */
    fun install(apkPath: String): Boolean {
        var result = false
        var dataOutputStream: DataOutputStream? = null
        var errorStream: BufferedReader? = null
        try {
            // 申请su权限
            val process = Runtime.getRuntime().exec("su")
            dataOutputStream = DataOutputStream(process.outputStream)
            // 执行pm install命令
            val command = "pm install -r $apkPath\n"
            dataOutputStream.write(command.toByteArray(Charset.forName("utf-8")))
            dataOutputStream.flush()
            dataOutputStream.writeBytes("exit\n")
            dataOutputStream.flush()
            process.waitFor()
            errorStream = BufferedReader(InputStreamReader(process.errorStream))
            val msg = StringBuilder()
            // 读取命令的执行结果
            errorStream.forEachLine {
                msg.append(it)
            }
            Log.d("TAG", "install msg is $msg")
            // 如果执行结果中包含Failure字样就认为是安装失败，否则就认为安装成功
            if (!msg.toString().contains("Failure")) {
                result = true
            }
        } catch (e: Exception) {
            Log.e("TAG", e.message, e)
        } finally {
            try {
                dataOutputStream?.close()
                errorStream?.close()
            } catch (e: IOException) {
                Log.e("TAG", e.message, e)
            }

        }
        return result
    }

    /**
     * 将本应用置顶到最前端
     * 当本应用位于后台时，则将它切换到最前端
     *
     * @param context
     */
    fun setTopApp(context: Context) {
        if (!AppUtils.isAppForeground()) {
            /**获取ActivityManager */
            val activityManager = context.getSystemService(ACTIVITY_SERVICE) as ActivityManager
            /**获得当前运行的task(任务) */
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                @Suppress("DEPRECATION")
                val taskInfoList = activityManager.getRunningTasks(100)
                for (taskInfo in taskInfoList) {
                    /**找到本应用的 task，并将它切换到前台 */
                    if (taskInfo.topActivity?.packageName == context.packageName) {
                        activityManager.moveTaskToFront(taskInfo.id, 0)
                        break
                    }
                }
            }
        }
    }

    // 获取应用占用的内存(单位为KB)
    /**
     * VmSize: 虚拟内存大小。 整个进程使用虚拟内存大小，是VmLib, VmExe, VmData, 和 VmStk的总和。
     * VmLck: 虚拟内存锁。 进程当前使用的并且加锁的虚拟内存总数
     * VmRSS: 虚拟内存驻留集合大小。 这是驻留在物理内存的一部分。它没有交换到硬盘。它包括代码，数据和栈。
     * VmData: 虚拟内存数据。 堆使用的虚拟内存。
     * VmStk: 虚拟内存栈 栈使用的虚拟内存
     * VmExe:  可执行的虚拟内存 可执行的和静态链接库所使用的虚拟内存
     * VmLib: 虚拟内存库 动态链接库所使用的虚拟内存
     */
    fun getAppMemory(): String {
        var vmRss = ""
        var vmSize = ""
        try {
            val pid = android.os.Process.myPid()
            val reader = BufferedReader(InputStreamReader(FileInputStream("/proc/$pid/status")))
            var load: String? = reader.readLine()
            while (load != null) {
//                LogUtils.i("file read line : $load")
                load = load.replace(" ", "")
                val infoList = load.split(":")
                if (infoList[0] == "VmRSS") {
                    vmRss = infoList[1]
                }
                if (infoList[0] == "VmSize") {
                    vmSize = infoList[1]
                }
                if (vmRss.isNotEmpty() && vmSize.isNotEmpty()) {
                    break
                }
                load = reader.readLine()
            }
            reader.close()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }

        return "$vmRss/$vmSize"
    }
}